package com.clp.protocol.iec104.iec104.client.pipeline;

import com.clp.protocol.iec104.iec104.client.Master;
import com.clp.protocol.iec104.iec104.client.pipeline.check.CheckApduInHandler;
import com.clp.protocol.iec104.iec104.client.pipeline.codec.ApduToBytesMasterEncoder;
import com.clp.protocol.iec104.iec104.client.pipeline.codec.BytesToApduMasterDecoder;
import com.clp.protocol.iec104.iec104.client.pipeline.codec.CompleteApduMasterDecoder;
import com.clp.protocol.iec104.iec104.client.pipeline.handler.ControlMasterHandler;
import com.clp.protocol.iec104.iec104.client.pipeline.handler.MasterHandlersSupplier;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;

import java.util.List;

public class Iec104ChannelInitializer extends ChannelInitializer<SocketChannel> {
    private final Master master;
    private final MasterHandlersSupplier supplier;

    public Iec104ChannelInitializer(Master master, MasterHandlersSupplier supplier) {
        this.master = master;
        this.supplier = supplier;
    }

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        // 解码器，解决粘包半包问题
        ch.pipeline().addLast(new CompleteApduMasterDecoder(master));
        // 处理器，检查信息内容是否合法
        ch.pipeline().addLast(new CheckApduInHandler(master));
        // 解码器，将协议内容转换成入站消息对象
        ch.pipeline().addLast(new BytesToApduMasterDecoder(master));
        // 编码器，将出站消息对象转换成协议内容
        ch.pipeline().addLast(new ApduToBytesMasterEncoder(master));
        // 总控制器,但不实际处理报文，出入站都经过
        ch.pipeline().addLast(new ControlMasterHandler(master));

        // U帧处理器
//        ch.pipeline().addLast(new UTypeMasterHandler(master));
//        // S帧处理器
//        ch.pipeline().addLast(new STypeMasterHandler(master));
//        // I帧处理器
//        ch.pipeline().addLast(new ITypeMasterHandler(master));

        // 添加自定义处理器
        addCustomHandlersTo(ch.pipeline());
    }

    private void addCustomHandlersTo(ChannelPipeline pipeline) {
        if (pipeline == null) return;
        if (supplier != null) {
            List<DuplexMasterHandler> handlers = supplier.get(master);
            if (handlers != null) {
                handlers.forEach(pipeline::addLast);
            }
        }
    }
}
